package cn.com.utils;

import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.parser.OpenAPIV3Parser;
import lombok.extern.slf4j.Slf4j;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;


/**
 * swagger解析器util
 *
 * @author LiuGuodong
 * @date 2024/08/26
 */
@Slf4j
public class SwaggerParserUtil {

    public static final String TAB = "\t";
    public static String FILE_PATH = "/api/v1/aimarket";
    public static final String PREFIX = "E:\\cloud_star\\240911东莞大模型项目\\接口\\";
    public static final Set<String> names = new TreeSet<>();
    public static List<String> oldApi = new ArrayList<>();
    public static long fastTime = 11728370916702L;


    public static void main(String[] args) throws FileNotFoundException {
        // 加载老接口
        loadOldInterface();
        // 解析yaml文件
        Set<String> yaml = FileUtil.getFileName(PREFIX, "json");
        Set<String> resultsSet = new TreeSet<>();
        yaml.forEach(
                file -> {
                    Set<String> urls = Set.of();
                    // 解析yaml文件
                    try (FileInputStream inputStream = new FileInputStream(PREFIX + file)) {
                        urls = parseOpenAPI(inputStream);
                    } catch (IOException e) {
                        log.error("Failed to parse Swagger document.", e);
                    }
                    //过滤掉不需要的接口

                    // 输出结果
                    resultsSet.addAll(urls);
                    FileUtil.writeToFile(urls, PREFIX + file.replace(".yaml", "") + "output.txt");
                    System.out.println("Done with " + file);
                }
        );
        FileUtil.writeToFile(resultsSet, PREFIX + "ALL-output.txt");
    }

    /**
     * 加载旧接口
     */
    private static void loadOldInterface() {
        oldApi = Optional.ofNullable(FileUtil.getReadAllLines(PREFIX + "old-api.txt")).orElse(List.of())
                .stream().map(line -> {
                    try {
                        String[] split = line.trim().split(TAB);

                        // 138262119089 	安全组-BMS列表查询	GET	api/resource/v1/security_groups/bms/list
                        String[] nameAndModuleName = split[1].split("-");
                        String name = nameAndModuleName[0].trim();
                        String model = name;
                        if (nameAndModuleName.length > 1) {
                            model = nameAndModuleName[1].trim();
                        }
                        return split[0] + TAB + name + TAB + split[2] + TAB + split[3] + TAB + model;
                    } catch (Exception e) {
                        System.out.println("解析失败：" + line);
                        throw new RuntimeException(e);
                    }
                }).collect(Collectors.toList());
    }

    public static Set<String> parseOpenAPI(InputStream inputStream) {
        Set<String> tags = new TreeSet<>();
        OpenAPI openapi = null;
        try {
            openapi = new OpenAPIV3Parser().readContents(new String(inputStream.readAllBytes())).getOpenAPI();
        } catch (IOException e) {
            log.error("Failed to parse Swagger document.", e);
            return tags;
        }

        if (openapi == null || openapi.getPaths() == null) {
            log.error("No paths found in the OpenAPI definition.");
            return tags;
        }
        String url = openapi.getServers().stream().findFirst().orElse(new Server()).getUrl();
        FILE_PATH = url.replace("http://127.0.0.1:38188/", "");
        // 遍历所有的路径
        for (Map.Entry<String, PathItem> pathEntry : openapi.getPaths().entrySet()) {
            String path = pathEntry.getKey();
            PathItem pathItem = pathEntry.getValue();

            // 获取路径下的所有方法（GET, POST, etc.）
            Map<PathItem.HttpMethod, Operation> operations = pathItem.readOperationsMap();
            for (Map.Entry<PathItem.HttpMethod, Operation> operationEntry : operations.entrySet()) {
                PathItem.HttpMethod method = operationEntry.getKey();
                Operation operation = operationEntry.getValue();

                int endIndex = path.substring(1).indexOf("/");
                String service = path.substring(1, endIndex <= 0 ? path.length() : endIndex + 1);
                String model = operation.getTags().stream().findFirst().orElse(service).replace("默认目录/", "");
                //保证接口名称唯一
                String summary = ensureThatInterfaceNameIsUnique(operation, path, service, method, model);
                //path = (path.charAt(0) == '/' ? path.replaceFirst("/", "") : path);
                String api = (fastTime++) + TAB + summary + TAB + method + TAB + FILE_PATH + path + TAB + model;
                for (String line : oldApi) {
                    String[] split = line.split(TAB);
                    if (isContains(split, api.split(TAB))) {
                        api = split[0] + TAB + summary + TAB + method + TAB + FILE_PATH + path + TAB + model;
                        break;
                    }
                }

                tags.add(api);
            }
        }
        return tags;
    }


    /**
     * 是否包含 或者在同一模块
     *
     * @param arr arr
     * @return boolean
     */
    private static boolean isContains(String[] arr, String[] split) {
        return StrUtil.equals(arr[3], split[3]) && arr[2].equalsIgnoreCase(split[2]);
    }
    /**
     * 确保接口名称唯一
     *
     * @param operation 操作
     * @param path      路径
     * @param service   服务
     * @param method    方法
     * @param model     模型
     * @return {@link String }
     */
    private static String ensureThatInterfaceNameIsUnique(Operation operation, String path, String service, PathItem.HttpMethod method, String model) {
        String summary = operation.getSummary() == null ? "" : operation.getSummary();
        if (names.contains(summary)) {
            summary = path.replaceAll("/", " ")
                    .replaceAll("\\{", "")
                    .replaceAll("}", "")
                    .replace(service, "");
            summary = summary.trim();
            if (StrUtil.isBlank(summary)) {
                String name = method.name();
                // post 创建  get 查询  put 更新  delete 删除
                if ("POST".equalsIgnoreCase(name)) {
                    summary = "创建 " + model;
                } else if ("GET".equalsIgnoreCase(name)) {
                    summary = "查询 " + model;
                } else if ("PUT".equalsIgnoreCase(name)) {
                    summary = "更新 " + model;
                } else if ("DELETE".equalsIgnoreCase(name)) {
                    summary = "删除 " + model;
                } else {
                    summary = name + " " + model;
                }
            }
        }
        names.add(summary);

        return summary;
    }

}
